<html>
 <head>
  <meta charset="UTF-8">
 </head>
 <body>
  <p data-lake-id="uc7e3eee1" id="uc7e3eee1"><span data-lake-id="uca63e6ed" id="uca63e6ed">关于lambda表达式，有人可能会有质疑，因为网上有人说他并不是语法糖。其实我想纠正下这个说法。</span><strong><span data-lake-id="u34218b24" id="u34218b24">Labmda表达式不是匿名内部类的语法糖，但是他也是一个语法糖。实现方式其实是依赖了几个JVM底层提供的lambda相关api。</span></strong></p>
  <p data-lake-id="u63eb4e7c" id="u63eb4e7c"><br></p>
  <p data-lake-id="u2df8c274" id="u2df8c274"><span data-lake-id="ud513793f" id="ud513793f">先来看一个简单的lambda表达式。遍历一个list：</span></p>
  <p data-lake-id="u875bb71e" id="u875bb71e"><br></p>
  <pre lang="java"><code>
public static void main(String... args) {
    List&lt;String&gt; strList = ImmutableList.of("Hollis", "公众号：Hollis", "博客：www.hollischuang.com");

    strList.forEach( s -&gt; { System.out.println(s); } );
}
</code></pre>
  <p data-lake-id="uae0b75d8" id="uae0b75d8"><br></p>
  <p data-lake-id="u607a4d87" id="u607a4d87"><span data-lake-id="uada67b33" id="uada67b33">为啥说他并不是内部类的语法糖呢，前面讲内部类我们说过，内部类在编译之后会有两个class文件，但是，包含lambda表达式的类编译后只有一个文件。</span></p>
  <p data-lake-id="u94d64d13" id="u94d64d13"><span data-lake-id="u7fb1ed31" id="u7fb1ed31">​</span><br></p>
  <p data-lake-id="uf9443016" id="uf9443016"><br></p>
  <p data-lake-id="ua2984fae" id="ua2984fae"><span data-lake-id="u5212b38d" id="u5212b38d">反编译后代码如下:</span></p>
  <p data-lake-id="ub0648a34" id="ub0648a34"><br></p>
  <pre lang="java"><code>
public static /* varargs */ void main(String ... args) {
    ImmutableList strList = ImmutableList.of((Object)"Hollis", (Object)"\u516c\u4f17\u53f7\uff1aHollis", (Object)"\u535a\u5ba2\uff1awww.hollischuang.com");
    strList.forEach((Consumer&lt;String&gt;)LambdaMetafactory.metafactory(null, null, null, (Ljava/lang/Object;)V, lambda$main$0(java.lang.String ), (Ljava/lang/String;)V)());
}

private static /* synthetic */ void lambda$main$0(String s) {
    System.out.println(s);
}
</code></pre>
  <p data-lake-id="u6ee53053" id="u6ee53053"><br></p>
  <p data-lake-id="uf8098c22" id="uf8098c22"><span data-lake-id="u336cef9e" id="u336cef9e">可以看到，在</span><code data-lake-id="u5339b5c4" id="u5339b5c4"><span data-lake-id="ueeb9ed7d" id="ueeb9ed7d">forEach</span></code><span data-lake-id="u00309baa" id="u00309baa">方法中，其实是调用了</span><code data-lake-id="u7f8091ec" id="u7f8091ec"><span data-lake-id="uc3d66132" id="uc3d66132">java.lang.invoke.LambdaMetafactory#metafactory</span></code><span data-lake-id="u1f9e3d6d" id="u1f9e3d6d">方法，该方法的第5个参数implMethod指定了方法实现。可以看到这里其实是调用了一个</span><code data-lake-id="u3ecdd9d5" id="u3ecdd9d5"><span data-lake-id="u7c1991ec" id="u7c1991ec">lambda$main$0</span></code><span data-lake-id="uef6036a6" id="uef6036a6">方法进行了输出。</span></p>
  <p data-lake-id="u99fb4ed2" id="u99fb4ed2"><br></p>
  <p data-lake-id="u7e2419d9" id="u7e2419d9"><span data-lake-id="u760d9329" id="u760d9329">再来看一个稍微复杂一点的，先对List进行过滤，然后再输出：</span></p>
  <p data-lake-id="u358778ac" id="u358778ac"><br></p>
  <pre lang="java"><code>
public static void main(String... args) {
    List&lt;String&gt; strList = ImmutableList.of("Hollis", "公众号：Hollis", "博客：www.hollischuang.com");

    List HollisList = strList.stream().filter(string -&gt; string.contains("Hollis")).collect(Collectors.toList());

    HollisList.forEach( s -&gt; { System.out.println(s); } );
}
</code></pre>
  <p data-lake-id="u6dc4e157" id="u6dc4e157"><br></p>
  <p data-lake-id="ua51f86b2" id="ua51f86b2"><span data-lake-id="u56e91848" id="u56e91848">反编译后代码如下：</span></p>
  <p data-lake-id="uc7896a48" id="uc7896a48"><br></p>
  <pre lang="java"><code>
public static /* varargs */ void main(String ... args) {
    ImmutableList strList = ImmutableList.of((Object)"Hollis", (Object)"\u516c\u4f17\u53f7\uff1aHollis", (Object)"\u535a\u5ba2\uff1awww.hollischuang.com");
    List&lt;Object&gt; HollisList = strList.stream().filter((Predicate&lt;String&gt;)LambdaMetafactory.metafactory(null, null, null, (Ljava/lang/Object;)Z, lambda$main$0(java.lang.String ), (Ljava/lang/String;)Z)()).collect(Collectors.toList());
    HollisList.forEach((Consumer&lt;Object&gt;)LambdaMetafactory.metafactory(null, null, null, (Ljava/lang/Object;)V, lambda$main$1(java.lang.Object ), (Ljava/lang/Object;)V)());
}

private static /* synthetic */ void lambda$main$1(Object s) {
    System.out.println(s);
}

private static /* synthetic */ boolean lambda$main$0(String string) {
    return string.contains("Hollis");
}
</code></pre>
  <p data-lake-id="uc31ba309" id="uc31ba309"><br></p>
  <p data-lake-id="u67af6420" id="u67af6420"><span data-lake-id="u90e9c4f0" id="u90e9c4f0">两个lambda表达式分别调用了</span><code data-lake-id="ub592035f" id="ub592035f"><span data-lake-id="u4e75c186" id="u4e75c186">lambda$main$1</span></code><span data-lake-id="u4fb2faff" id="u4fb2faff">和</span><code data-lake-id="ue6c95375" id="ue6c95375"><span data-lake-id="u7089915b" id="u7089915b">lambda$main$0</span></code><span data-lake-id="uea2a5a28" id="uea2a5a28">两个方法。</span></p>
  <p data-lake-id="u17163af9" id="u17163af9"><br></p>
  <p data-lake-id="u276edfda" id="u276edfda"><strong><span data-lake-id="ucd54b2e2" id="ucd54b2e2">所以，lambda表达式的实现其实是依赖了一些底层的api，在编译阶段，编译器会把lambda表达式进行解糖，转换成调用内部api的方式。</span></strong></p>
 </body>
</html>